-- $LastChangedDate: 2007-06-01 02:52:33 +0200 (Fri, 01 Jun 2007) $
-- $LastChangedRevision: 149 $
-- $LastChangedBy: vicente $

SEPARATE (Tareas.Gmonitores)

   -- Buscar un monitor libre u ocupado en la lista MList
PROCEDURE Get_Idle_Monitor_Emergencia (
      Mlist             : IN     Listas.Gmonitores_Lists.List_Type;
      M                 :    OUT Monitorptr;
      Monitores_Libre   : IN OUT Natural;
      Monitores_Ocupado : IN OUT Natural;
      Cl_Id             : IN     Task_Id) IS
   Encontrado : Boolean                               := False;
   It         : Listas.Gmonitores_Lists.List_Iterator;
   Nodo       : Nodomonitor;
BEGIN
   -- Primero intentar encontrar un monitor libre y decrementar asi monitores_libre
   -- Si no hay obtener uno que este ocupado y llamar a su entry emergencia para que deje
   -- de hacer lo que estaba haciendo. (aqui no decrementaremos monitores_libre).

   -- primero intentamos encontrar un monitor que este libre
   It := Listas.Gmonitores_Lists.First(Mlist);
   WHILE It /= Listas.Gmonitores_Lists.Last(Mlist) AND NOT
         Encontrado LOOP
      Nodo := Listas.Gmonitores_Lists.Value(It);
      IF Nodo.Estado = Libre THEN
         Encontrado:= True;
      ELSE
         It := Listas.Gmonitores_Lists.Succ(It);
      END IF;
   END LOOP;

   IF NOT Encontrado THEN
      -- intentamos ahora encontrar un monitor que este ocupado
      It := Listas.Gmonitores_Lists.First(Mlist);
      WHILE It /= Listas.Gmonitores_Lists.Last(Mlist) AND NOT
            Encontrado LOOP
         Nodo := Listas.Gmonitores_Lists.Value(It);
         IF Nodo.Estado = Ocupado THEN
            Encontrado:= True;
         ELSE
            It := Listas.Gmonitores_Lists.Succ(It);
         END IF;
      END LOOP;

      IF Encontrado THEN
         -- ha encontrado un monitor en estado ocupado
         M:= Nodo.Mptr;
         -- IMPORTANTE: hay que decirle al monitor que deje de hacer lo que hacia
         M.Emergencia;

         Print("get_idle_monitor_emergencia: asignado al cliente del aparato" & Image(Cl_Id) & " el monitor con ID "
            & Image(Nodo.Id) & " para atender la emergencia");
         -- actualizar el estado del monitor y los contadores de monitores disponibles
         Nodo.Estado := Ocupadoemergencia;
         Listas.Gmonitores_Lists.Update(It, Nodo);
         -- el monitor estaba ocupado
         -- ahora estara ocupado por emergencia
         Monitores_Ocupado := Monitores_Ocupado - 1;
      ELSE
         -- todos los monitores estaban en estado ocupado por emergencia
         M:= NULL;
         Print("get_idle_monitor_emergencia: No hay monitores libres para emergencias");
      END IF;
   ELSE
      -- habia encontrado un monitor en estado libre
      M:= Nodo.Mptr;
      Print("get_idle_monitor_emergencia: asignado al cliente del aparato " & Image(Cl_Id) & " el monitor con ID "
         & Image(Nodo.Id) & " para atender la emergencia");
      -- actualizar el estado del monitor y los contadores de monitores disponibles
      Nodo.Estado := Ocupadoemergencia;
      Listas.Gmonitores_Lists.Update(It, Nodo);
      -- el monitor ya no estara libre
      Monitores_Libre := Monitores_Libre - 1;
      -- log
      Log_Dec(Monitor_Libre);
   END IF;

END Get_Idle_Monitor_Emergencia;
